package TestSystemServer;

import java.io.*;
import java.net.*;
import java.sql.*;
import java.util.*;

import TestSystemUtil.*;

public class Server {
	public static Connection sqlconnect = null;
	public static PreparedStatement pst;
	public static ResultSet rs = null;
	public static Vector<ServerThread> connectingThreads = new Vector<ServerThread>();
	public static Vector<ServerThread> groupThreads = new Vector<ServerThread> ();
	public static int submitCount = 0;
	public static String level, field, question, choiceA, choiceB, choiceC, choiceD, answer;
	public static int id = 1;
	
	public static void main(String[] args) throws IOException {
		int port = 6789;
		Server serv = new Server();
		serv.listen(port);
	}
	
	public void listen(int port) throws IOException {
		ServerSocket servSock = new ServerSocket(port);
		System.out.println("Listening for connections on port: " + servSock.getLocalPort());
		sqlconnect = DBconnect.establishConnection();
		
		while(true) {
			Socket clntSock = servSock.accept();
			ServerThread thread = new ServerThread(clntSock, "Test+"+id++);
			add(thread);
			thread.start();
			System.out.println("Created and started Thread " + thread.getName());
		}
	}
	
	public static void broadcast(String username, boolean online) {
		String messageToClients; 
		if(online==true) {
			messageToClients = "ONLINE+" +username + "\n";
		} else {
			messageToClients = "OFFLINE+" +username+ "\n";
		}
		for(ServerThread tmp : connectingThreads) {
			if(tmp.online && !tmp.username.equals(username)) {
				try {
					BufferedWriter out = new BufferedWriter(new OutputStreamWriter(tmp.clntSock.getOutputStream()));
					System.out.println("Server's broadcasting: "+messageToClients + " to "+tmp.getName());
					out.write(messageToClients);
					out.flush();
				} catch (IOException e) {
					System.err.println("Broadcast: " +  e);
				}
			}
		}
			
	}
	
	public static void sendInviteMessage(String host, String target) {
		String messageToTarget = String.format("INVITE+%s+%s", host, target) + "\n";
		for(ServerThread tmp : connectingThreads) {
			if(tmp.username.equals(target)) {
				try {
					BufferedWriter out = new BufferedWriter(new OutputStreamWriter(tmp.clntSock.getOutputStream()));
					System.out.println("Server sent invite message: "+messageToTarget + " to "+tmp.getName());
					out.write(messageToTarget);
					out.flush();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void sendAcceptMessage(String host, String target) {
		String messageToHost = String.format("ACCEPT+%s", target) + "\n";
		for(ServerThread tmp : groupThreads) {
			if(tmp.username.equals(host)) {
				try {
					tmp.inGroup = true;
					BufferedWriter out = new BufferedWriter(new OutputStreamWriter(tmp.clntSock.getOutputStream()));
					System.out.println("Server sent accept message: "+ messageToHost + " to "+tmp.getName());
					out.write(messageToHost);
					out.flush();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	

	public static void sendDeclineMessage(String host, String target) {
		String messageToHost = String.format("DECLINE+%s", target) + "\n";
		for(ServerThread tmp : groupThreads) {
			if(tmp.username.equals(host)) {
				try {
					BufferedWriter out = new BufferedWriter(new OutputStreamWriter(tmp.clntSock.getOutputStream()));
					System.out.println("Server sent decline message: "+ messageToHost + " to "+tmp.getName());
					out.write(messageToHost);
					out.flush();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void sendGroupInfo() {
		String messageToGroup = "GROUPINFO";
		for(ServerThread tmp : groupThreads) {
			// tin sẽ có dạng: GROUPINFO - fullname/score - fullname/score - [fullname/score] - [fullname/score]
			messageToGroup = String.format(messageToGroup+"+%s/%s", tmp.fullname, String.valueOf(tmp.score));
		}
		messageToGroup = messageToGroup + "\n";
		for(ServerThread tmp : groupThreads) {
			try {
				BufferedWriter out = new BufferedWriter(new OutputStreamWriter(tmp.clntSock.getOutputStream()));
				System.out.println("Server sent group info: "+ messageToGroup + " to "+tmp.getName());
				out.write(messageToGroup);
				out.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void sendStartMessage() {
		String messageToGroup = "GROUPSTART" + "\n";
		for(ServerThread tmp : groupThreads) {
			try {
				BufferedWriter out = new BufferedWriter(new OutputStreamWriter(tmp.clntSock.getOutputStream()));
				System.out.println("Server sent start message: "+ messageToGroup + " to "+tmp.getName());
				out.write(messageToGroup);
				out.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void sendQuestionToGroup(String messageToGroup) {
		for(ServerThread tmp : groupThreads) {
			try {
				BufferedWriter out = new BufferedWriter(new OutputStreamWriter(tmp.clntSock.getOutputStream()));
				System.out.println("Server sent question message: "+ messageToGroup + " to "+tmp.getName());
				out.write(messageToGroup);
				out.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void sendResultToGroup() {
		String messageToGroup = "GROUPRESULT";
		for(ServerThread tmp : groupThreads) {
			messageToGroup = String.format(messageToGroup+"+%s/%s/%s/%s", tmp.fullname, String.valueOf(tmp.score), String.valueOf(tmp.second), tmp.clientAnswer);
		}
		messageToGroup = messageToGroup + "+" + answer;
		messageToGroup = messageToGroup + "\n";
		for(ServerThread tmp : groupThreads) {
			try {
				BufferedWriter out = new BufferedWriter(new OutputStreamWriter(tmp.clntSock.getOutputStream()));
				System.out.println("Server sent question message: "+ messageToGroup + " to "+tmp.getName());
				out.write(messageToGroup);
				out.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		submitCount = 0;
	}
	
	public static ServerThread getThread(String username) {
		for(ServerThread tmp : groupThreads) {
			if(tmp.username.equals(username)) return tmp;
		}
		return null;
	}
	public synchronized void add(ServerThread st) {
		connectingThreads.add(st);
	}
	
	public synchronized void remove(ServerThread st) {
		connectingThreads.remove(st);
	}
}